package com.atguigu.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.atguigu.client.OrderFeignClient;
import com.atguigu.config.AlipayConfig;
import com.atguigu.constant.MqConst;
import com.atguigu.entity.OrderInfo;
import com.atguigu.entity.PaymentInfo;
import com.atguigu.enums.PaymentStatus;
import com.atguigu.enums.PaymentType;
import com.atguigu.enums.ProcessStatus;
import com.atguigu.mapper.PaymentInfoMapper;
import com.atguigu.service.PaymentInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 支付信息表 服务实现类
 * </p>
 *
 * @author fumeng
 * @since 2021-11-11
 */
@Service
public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfo> implements PaymentInfoService {

    @Autowired
    private OrderFeignClient orderFeignClient;
    @Autowired
    private AlipayClient alipayClient;
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    public String createQrCode(Long orderId) throws Exception {
        //1.根据订单id查询订单信息
        OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderId);
        //2.保存支付信息
        savePaymentInfo(orderInfo,PaymentType.ALIPAY.name());
        //3.调用支付宝返回二维码的工具类
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //设置支付成功之后的异步通知
        request.setNotifyUrl(AlipayConfig.notify_payment_url);
        //设置支付成功之后的同步通知
        request.setReturnUrl(AlipayConfig.return_payment_url);
        JSONObject bizContent = new JSONObject();
        //商户订单号
        bizContent.put("out_trade_no", orderInfo.getOutTradeNo());
        //订单总金额
        bizContent.put("total_amount", orderInfo.getTotalMoney());
        //订单标题
        bizContent.put("subject", "商品汇");
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        request.setBizContent(bizContent.toString());
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        if(response.isSuccess()){
            return response.getBody();
        } else {
            System.out.println("调用失败");
        }
        return null;
    }

    @Override
    public PaymentInfo getPaymentInfo(String outTradeNo, String paymentType) {
        QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("out_trade_no",outTradeNo);
        wrapper.eq("payment_type",paymentType);
        PaymentInfo paymentInfo = baseMapper.selectOne(wrapper);
        return paymentInfo;

    }


    //支付成功之后修改订单状态
    @Override
    public void updatePaymentInfo(String outTradeNo, String name, Map<String, String> paramMap) {
        PaymentInfo dbPaymentInfo = getPaymentInfo(outTradeNo, name);
        //判断查询到的数据支付状态
        if (dbPaymentInfo.getPaymentStatus().equals(PaymentStatus.PAID.name()) ||
                dbPaymentInfo.getPaymentStatus().equals(PaymentStatus.ClOSED.name())) {
            // 此时需要return
            return;
        }
        //设置更新的内容
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setPaymentStatus(PaymentStatus.PAID.name());
        paymentInfo.setCallbackTime(new Date());
        paymentInfo.setCallbackContent(paramMap.toString());
        paymentInfo.setTradeNo(paramMap.get("trade_no"));
        //设置更新的条件
        QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("out_trade_no",outTradeNo);
        baseMapper.update(paymentInfo,wrapper);

        //更新订单信息 需要在订单系统shop-order中编写代码
        rabbitTemplate.convertAndSend(MqConst.PAY_ORDER_EXCHANGE, MqConst.PAY_ORDER_ROUTE_KEY, dbPaymentInfo.getOrderId());

    }

    //退款
    @Override
    public boolean refund(Long orderId) throws Exception {
        // 根据退款接口：(out_trade_no || trade_no) && refund_amount
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        // out_trade_no ,在订单表，交易记录表都有，并这两个是同一个值！
        OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderId);
        // 创建一个map
        HashMap<String, Object> refundDataMap = new HashMap<>();
        refundDataMap.put("out_trade_no",orderInfo.getOutTradeNo());
        refundDataMap.put("refund_amount",orderInfo.getTotalMoney());
        refundDataMap.put("refund_reason","退款原因");

        request.setBizContent(JSON.toJSONString(refundDataMap));
        AlipayTradeRefundResponse response = alipayClient.execute(request);;
        if(response.isSuccess()){
            //说退款成功了, 需要关闭支付宝的交易状态！同时还需要关闭交易记录。
            System.out.println("调用成功");
            //先关闭交易记录
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setPaymentStatus(ProcessStatus.CLOSED.name());
            //更新条件
            QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("out_trade_no",paymentInfo.getOutTradeNo());
            baseMapper.update(paymentInfo,wrapper);
            // 如果支付宝更新了交易状态，就不能继续退款了！
            return true;
        } else {
            System.out.println("调用失败");
            return false;
        }

    }

    //5.查询阿里内部订单信息
    @Override
    public boolean queryAlipayTrade(Long orderId) throws Exception {
        OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderId);
        HashMap<String, Object> map = new HashMap<>();
        map.put("out_trade_no",orderInfo.getOutTradeNo());
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent(JSON.toJSONString(map));
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            return true;
        } else {
            return false;
        }

    }

    //4.关闭交易接口 http://127.0.0.1:8005/payment/closeAlipayTrade/28
    @Override
    public boolean closeAlipayTrade(Long orderId) throws Exception {
        OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderId);
        HashMap<String, Object> map = new HashMap<>();
        map.put("out_trade_no",orderInfo.getOutTradeNo());
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        request.setBizContent(JSON.toJSONString(map));
        AlipayTradeCloseResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            return true;
        } else {
            return false;
        }

    }

    //关闭订单信息为close

    @Override
    public void closePaymentInfo(Long orderId) {
        QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id",orderId);
        Integer count = baseMapper.selectCount(wrapper);
        if (count==0){
            return;
        }
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setPaymentStatus(PaymentStatus.ClOSED.name());
        baseMapper.update(paymentInfo,wrapper);

    }

    //支付成功，插入数据库
    private void savePaymentInfo(OrderInfo orderInfo, String paymentType) {
        //订单Id和支付方式 这个两个作为一个标准不能重复
        QueryWrapper<PaymentInfo> paymentInfoQueryWrapper = new QueryWrapper<>();
        paymentInfoQueryWrapper.eq("order_id",orderInfo.getId());
        paymentInfoQueryWrapper.eq("payment_type",paymentType);
        //判断数据库是否有这个订单
        Integer count = baseMapper.selectCount(paymentInfoQueryWrapper);

        if (count>0){
            return;
        }
        //创建一个paymentInfo 对象
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setOutTradeNo(orderInfo.getOutTradeNo());
        paymentInfo.setOrderId(orderInfo.getId()+"");
        paymentInfo.setPaymentType(paymentType);
        paymentInfo.setPaymentMoney(orderInfo.getTotalMoney());
        paymentInfo.setPaymentContent(orderInfo.getTradeBody());
        paymentInfo.setPaymentStatus(PaymentStatus.UNPAID.name());
        paymentInfo.setCreateTime(new Date());
        baseMapper.insert(paymentInfo);

    }
}
